<?php

use App\Library\MySeasLog;
use Illuminate\Contracts\Database\Query\Expression;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;

/**
 * fail
 * @param int $code
 * @return JsonResponse
 */
function fail(int $code = -1): JsonResponse
{
    $arr = [
        'code' => $code,
        'message' => __('errorCode.' . $code),
//        'requestId' => app('xrl-trace')->getTrace(),
        'timestamp' => now()->format('Y-m-d H:i:s.u'),
    ];
    MySeasLog::warning($arr);
    return response()->json($arr);
}

/**
 * success
 * @param mixed $data
 * @param string $msg
 * @return JsonResponse
 */
function success(mixed $data = [], string $msg = 'success'): JsonResponse
{
    $jsonData = [
        'code' => 200,
        'msg' => $msg,
        'data' => $data,
//        'requestId' => app('xrl-trace')->getTrace(),
        'timestamp' => now()->format('Y-m-d H:i:s.u'),
    ];
    MySeasLog::notice($jsonData);
    return response()->json($jsonData);
}

/**
 * failCodeMessage
 * @param int $code
 * @param string $message
 * @return JsonResponse
 */
function failCodeMessage(int $code = -1, string $message = ''): JsonResponse
{
    $jsonData = [
        "code" => $code,
        "message" => $message,
//        'requestId' => app('xrl-trace')->getTrace(),
        'timestamp' => now()->format('Y-m-d H:i:s.u'),
    ];
    MySeasLog::warning($jsonData);
    return response()->json($jsonData);
}

/**
 * failMessage
 * @param string $message
 * @return JsonResponse
 */
function failMessage(string $message = ''): JsonResponse
{
    return failCodeMessage(-1, $message);
}

/**
 * payLog
 * @param string|array|null $string |array $string $string
 * @return void
 */
function payLog(string|array|null $string = null): void
{
    if (is_null($string)) $string = random();
    else if (is_array($string)) $string = print_r($string, true);
    Storage::append('pay/' . now()->toDateString() . '.log', now()->toDateTimeString('microsecond') . ' ' . $string);
}

/**
 * random
 * @param int $number
 * @param int $num
 * @param string $str
 * @return string
 */
function random(int $number = 6, int $num = 0, string $str = ''): string
{
    if ($num === 0) return Str::random($number);
    for ($i = 0; $i < $number; $i++) $str .= Arr::random(range(0, 9));
    return $str;
}

/**
 * prod
 * @return bool
 */
function prod(): bool
{
    if (config('app.env') === 'production') return true;
    else if (str_contains(config('app.url'), '127.0.0.1')) return false;
    else if (str_contains(config('app.url'), 'test.')) return false;
    else if (config('app.env') === 'local') return false;
    return true;
}

/**
 * getCacheUploadFile
 * @param string $serialNumber
 * @return ?string
 */
function getCacheUploadFile(string $serialNumber): ?string
{
    return DB::table('upload_File')->where('serial_number', $serialNumber)->value('mime_type');
}

/**
 * serialNumber
 * @param int $number
 * @return string
 */
function serialNumber(int $number = 20): string
{
    if ($number === 20) return now()->format('YmdHisu');
    else if ($number > 20) return now()->format('YmdHisu') . random($number - 20, 1);
    else return random($number, 1);
}

/**
 * 将下划线式命名转换为驼峰式命名
 * @param string|array $obj
 * @param array $arr
 * @return array|string
 */
function lineToHump(string|array $obj, array $arr = []): array|string
{
    if (is_string($obj)) return Str::camel($obj);
    else if (array_key_first($obj) === 0) foreach ($obj as $v) $arr[] = Str::camel($v);
    else foreach ($obj as $k => $v) $arr[Str::camel($k)] = $v;
    return $arr;
}


/**
 * 将驼峰式命名转换为下划线式命名
 * @param string|array $obj
 * @param array $arr
 * @return string|array
 */
function humpToLine(string|array $obj, array $arr = []): string|array
{
    if (is_string($obj)) return strtolower(Str::snake(lcfirst($obj)));
    else if (array_key_first($obj) === 0) {
        foreach ($obj as $k => $v) {
            if ($v instanceof Expression) continue;
            else if (is_array($v)) $obj[$k] = humpToLine($v);
            else $obj[$k] = strtolower(Str::snake(lcfirst($v)));
        }
        return $obj;
    } else {
        foreach ($obj as $k => $v) $arr[strtolower(Str::snake(lcfirst($k)))] = $v;
        return $arr;
    }
}

/**
 * Q
 * @param mixed ...$args
 * @return mixed
 */
function Q(...$args): mixed
{
    if (empty($args[0])) return null;
    else if (count($args) === 1) return $args[0];
    $v = $args[0];
    for ($i = 1; $i < count($args); $i++) {
        $arg = $args[$i];
        if (isset($v->$arg)) $v = $v->$arg;
        else if (isset($v[$arg])) $v = $v[$arg];
        else return null;
    }
    return $v;
}

/**
 * delZero
 * @param string|null $str
 * @return string|null
 */
function delZero(?string $str = null): ?string
{
    if (is_null($str)) return null;
    return Str::contains($str, '.') ? Str::rtrim(Str::rtrim($str, '0'), '.') : $str;
}

function maskIdCard($idCard, $start = 3, $end = 7): string
{
    $length = strlen($idCard);
    $mask = str_repeat('*', $length - $start - $end);
    return substr($idCard, 0, $start) . $mask . substr($idCard, -$end);
}

function maskMobile($mobile): string
{
    return substr($mobile, 0, 3) . "****" . substr($mobile, 7);
}

function getAge($number): int
{
    if (strlen($number) == 18) {
        $year = substr($number, 6, 4);
        $monthday = substr($number, 10, 4);
    } else {
        $birthDay = date('Ymd', strtotime($number));
        $year = substr($birthDay, 0, 4);
        $monthday = substr($birthDay, 4, 4);
    }
    $age = date('Y') - $year;
    if ($monthday >= date('md')) $age++;
    return $age;
}

function getServiceDate($data)
{
    $startDate = new DateTime($data);
// 获取当前日期
    $endDate = new DateTime();

// 计算日期差
    $interval = $startDate->diff($endDate);

// 获取总月数
    $totalMonths = $interval->format('%m') + ($interval->format('%y') * 12); // 月份转换为年并加上年份的完整月数
    $totalYears = $totalMonths / 12; // 将月数转换为年数，这将包括不满一年的月份在内

    return $totalMonths;
}
